package org.nnxy.foodboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.nnxy.foodboot.entity.RecipeSimilarity;
import org.nnxy.foodboot.mapper.RecipeSimilarityMapper;
import org.nnxy.foodboot.service.RecipeSimilarityService;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * 食谱相似度服务实现类
 */
@Service
@RequiredArgsConstructor
public class RecipeSimilarityServiceImpl extends ServiceImpl<RecipeSimilarityMapper, RecipeSimilarity> implements RecipeSimilarityService {

    private final RecipeSimilarityMapper recipeSimilarityMapper;
    
    // 各相似度维度的权重
    private static final BigDecimal CONTENT_WEIGHT = new BigDecimal("0.20");
    private static final BigDecimal TASTE_WEIGHT = new BigDecimal("0.30");
    private static final BigDecimal NUTRITION_WEIGHT = new BigDecimal("0.20");
    private static final BigDecimal INGREDIENT_WEIGHT = new BigDecimal("0.30");

    @Override
    public RecipeSimilarity getSimilarityBetweenRecipes(Integer recipeId1, Integer recipeId2) {
        if (recipeId1 == null || recipeId2 == null) {
            return null;
        }
        
        // 确保ID1 < ID2以避免重复记录
        if (recipeId1 > recipeId2) {
            Integer temp = recipeId1;
            recipeId1 = recipeId2;
            recipeId2 = temp;
        }
        
        LambdaQueryWrapper<RecipeSimilarity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecipeSimilarity::getRecipeId1, recipeId1)
                .eq(RecipeSimilarity::getRecipeId2, recipeId2);
        
        return getOne(queryWrapper);
    }

    @Override
    public boolean saveOrUpdateSimilarity(Integer recipeId1, Integer recipeId2, 
                                         BigDecimal contentSimilarity, BigDecimal tasteSimilarity, 
                                         BigDecimal nutritionSimilarity, BigDecimal ingredientSimilarity) {
        if (recipeId1 == null || recipeId2 == null) {
            return false;
        }
        
        // 确保ID1 < ID2以避免重复记录
        if (recipeId1 > recipeId2) {
            Integer temp = recipeId1;
            recipeId1 = recipeId2;
            recipeId2 = temp;
            
            // 交换相应的相似度值
            BigDecimal tempSimilarity = contentSimilarity;
            contentSimilarity = tasteSimilarity;
            tasteSimilarity = tempSimilarity;
        }
        
        // 计算综合相似度
        BigDecimal overallSimilarity = calculateOverallSimilarity(
                contentSimilarity, tasteSimilarity, nutritionSimilarity, ingredientSimilarity);
        
        // 查找现有记录
        RecipeSimilarity similarity = getSimilarityBetweenRecipes(recipeId1, recipeId2);
        
        if (similarity == null) {
            // 创建新记录
            similarity = new RecipeSimilarity();
            similarity.setRecipeId1(recipeId1);
            similarity.setRecipeId2(recipeId2);
            similarity.setContentSimilarity(contentSimilarity);
            similarity.setTasteSimilarity(tasteSimilarity);
            similarity.setNutritionSimilarity(nutritionSimilarity);
            similarity.setIngredientSimilarity(ingredientSimilarity);
            similarity.setOverallSimilarity(overallSimilarity);
            
            return save(similarity);
        } else {
            // 更新现有记录
            similarity.setContentSimilarity(contentSimilarity);
            similarity.setTasteSimilarity(tasteSimilarity);
            similarity.setNutritionSimilarity(nutritionSimilarity);
            similarity.setIngredientSimilarity(ingredientSimilarity);
            similarity.setOverallSimilarity(overallSimilarity);
            
            return updateById(similarity);
        }
    }

    @Override
    public BigDecimal calculateOverallSimilarity(BigDecimal contentSimilarity, BigDecimal tasteSimilarity, 
                                               BigDecimal nutritionSimilarity, BigDecimal ingredientSimilarity) {
        // 处理null值
        contentSimilarity = contentSimilarity != null ? contentSimilarity : BigDecimal.ZERO;
        tasteSimilarity = tasteSimilarity != null ? tasteSimilarity : BigDecimal.ZERO;
        nutritionSimilarity = nutritionSimilarity != null ? nutritionSimilarity : BigDecimal.ZERO;
        ingredientSimilarity = ingredientSimilarity != null ? ingredientSimilarity : BigDecimal.ZERO;
        
        // 加权计算总体相似度
        BigDecimal weightedContent = contentSimilarity.multiply(CONTENT_WEIGHT);
        BigDecimal weightedTaste = tasteSimilarity.multiply(TASTE_WEIGHT);
        BigDecimal weightedNutrition = nutritionSimilarity.multiply(NUTRITION_WEIGHT);
        BigDecimal weightedIngredient = ingredientSimilarity.multiply(INGREDIENT_WEIGHT);
        
        BigDecimal overallSimilarity = weightedContent
                .add(weightedTaste)
                .add(weightedNutrition)
                .add(weightedIngredient);
        
        // 保留4位小数
        overallSimilarity = overallSimilarity.setScale(4, RoundingMode.HALF_UP);
        
        return overallSimilarity;
    }

    @Override
    public List<Integer> getSimilarRecipeIds(Integer recipeId, Integer limit) {
        if (recipeId == null || limit == null || limit <= 0) {
            return List.of();
        }
        
        return recipeSimilarityMapper.getSimilarRecipeIds(recipeId, limit);
    }

    @Override
    public List<Integer> getSimilarTasteRecipeIds(Integer recipeId, Integer limit) {
        if (recipeId == null || limit == null || limit <= 0) {
            return List.of();
        }
        
        return recipeSimilarityMapper.getSimilarTasteRecipeIds(recipeId, limit);
    }

    @Override
    public List<Integer> getSimilarNutritionRecipeIds(Integer recipeId, Integer limit) {
        if (recipeId == null || limit == null || limit <= 0) {
            return List.of();
        }
        
        return recipeSimilarityMapper.getSimilarNutritionRecipeIds(recipeId, limit);
    }
} 